/*
 * Project Porcupine
 * Copyright (C) 2012  Team Porcupine
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.towerdive.porcupine.controls;

import com.jme3.export.InputCapsule;
import com.jme3.export.JmeExporter;
import com.jme3.export.JmeImporter;
import com.jme3.export.OutputCapsule;
import com.jme3.renderer.RenderManager;
import com.jme3.renderer.ViewPort;
import com.jme3.scene.Spatial;
import com.jme3.scene.control.AbstractControl;
import com.jme3.scene.control.Control;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * A very basic way to implement receiving damage, losing health, and dying.
 * At some point this should probably made abstract and sub-classed with
 * various systems for testing. Also, "static" objects like furniture should
 * probably have a different sub-class than "active" objects like creature,
 * since "active" objects might have more complex damage modeling. The player
 * probably needs a sub-class as well.
 * 
 * @author Martin "quill18" Glaude <quill18@towerdive.com>
 */
public class DamageControl extends AbstractControl {
    //Any local variables should be encapsulated by getters/setters so they
    //appear in the SDK properties window and can be edited.
    //Right-click a local variable to encapsulate it with getters and setters.
    
    /**
     * Hit points. When health <= 0, object is dead.
     */
    private float health = 100f;
    
    /**
     * This flags when an object still exists in the world, but is in the process
     * of playing a death animation or something and shouldn't perform any
     * AI actions and such.
     * DO NOT WRITE TO THIS DIRECTLY. Subclasses may override setDying()
     */
    private boolean dying = false;
    
    public void receiveDamage(DamageInformation damageInformation) {
        health -= damageInformation.getAmount();
        if (health <= 0) {
            setDying(true);
        }
    }

    @Override
    protected void controlUpdate(float tpf) {
        //TODO: add code that controls Spatial,
        //e.g. spatial.rotate(tpf,tpf,tpf);
        
        //receiveDamage(new DamageInformation(10*tpf));
        
        //Logger.getLogger("").log(Level.SEVERE, "Unit health: " + getHealth());
        
        if(isDying()) {
            spatial.removeFromParent();
        }
    }
    
    @Override
    protected void controlRender(RenderManager rm, ViewPort vp) {
        //Only needed for rendering-related operations,
        //not called when spatial is culled.
    }
    
    public Control cloneForSpatial(Spatial spatial) {
        DamageControl control = new DamageControl();
        //TODO: copy parameters to new Control
        control.setSpatial(spatial);
        return control;
    }
    
    @Override
    public void read(JmeImporter im) throws IOException {
        super.read(im);
        InputCapsule in = im.getCapsule(this);
        //TODO: load properties of this Control, e.g.
        //this.value = in.readFloat("name", defaultValue);
    }
    
    @Override
    public void write(JmeExporter ex) throws IOException {
        super.write(ex);
        OutputCapsule out = ex.getCapsule(this);
        //TODO: save properties of this Control, e.g.
        //out.write(this.value, "name", defaultValue);
    }

    /**
     * @return the health
     */
    public float getHealth() {
        return health;
    }

    /**
     * @param health the health to set
     */
    public void setHealth(float health) {
        this.health = health;
    }

    /**
     * @return the dying
     */
    public boolean isDying() {
        return dying;
    }

    /**
     * @param dying the dying to set
     */
    public void setDying(boolean dying) {
        this.dying = dying;
    }
}
